package task

import (
	// "sync"
	"time"

	"gitee.com/kobeyyf/mkm/service/model"
)

type dProduct struct {
	*model.LogProduct
	doLog  *model.LogProductDevice
	isDone bool
	img    string
}

// 执行设备
// 维护设备的执行情况
type Device struct {
	retry int
	*model.Device

	nextC chan *dProduct

	productMap map[uint64]*dProduct
	// doneProductMapMux *sync.Mutex

	isDone       bool
	successCount int
}

func NewDevice(retry int, info *model.Device, products []*model.LogProduct) *Device {

	d := &Device{
		Device: info,

		retry: retry,

		nextC: make(chan *dProduct),

		productMap: make(map[uint64]*dProduct, len(products)),
		// doneProductMap:    make(map[uint64]*dProduct, len(products)),
		// doneProductMapMux: new(sync.Mutex),
	}
	for _, p := range products {
		tmp := &dProduct{
			LogProduct: p,
			isDone:     false,
			doLog: &model.LogProductDevice{

				DeviceId: info.DeviceId,
				Name:     info.Name,
				Code:     info.Code,

				TaskId:    p.TaskId,
				ProductId: p.ProductId,
				IsSuccess: model.IS_N,
			},
		}
		d.productMap[p.ProductId] = tmp
		// d.doneProductMap[p.ProductId] = tmp
	}

	go d.run()

	return d
}
func (d *Device) run() {
	for i := 0; i < d.retry; i++ {
		for _, product := range d.productMap {
			if d.isDone {
				return
			}
			if product.isDone {
				continue
			}
			d.nextC <- product

		}
	}
	d.isDone = true
	close(d.nextC)
}
func (d *Device) AddDoneProdeuct(productId uint64, img string) {
	// d.doneProductMapMux.Lock()
	// defer d.doneProductMapMux.Unlock()

	p, has := d.productMap[productId]
	if has {
		d.successCount++
		p.isDone = true

		p.doLog.EndTime = time.Now().Unix()
		p.doLog.IsSuccess = model.IS_Y
		p.doLog.ImgUrl = img
		p.LogProduct.DeviceDone++
	}

}

func (d *Device) Next() (p *model.LogProduct) {
	if d.isDone {
		return nil
	}
	tmp, ok := <-d.nextC
	if ok {
		tmp.doLog.StartTime = time.Now().Unix()
		tmp.doLog.SendCount++
		return tmp.LogProduct
	}
	return nil
}

// 获取设备的执行状态
func (d *Device) Status() (isDone bool, logs []*model.LogProductDevice) {
	logs = make([]*model.LogProductDevice, 0, len(d.productMap))

	// d.productMapMux.Lock()
	// defer d.productMapMux.Unlock()

	for _, p := range d.productMap {
		logs = append(logs, p.doLog)
	}

	return d.isDone, logs
}

func (d *Device) Stop() {
	d.isDone = true
	select {
	case <-d.nextC:
	case <-time.After(time.Microsecond):
	}

	close(d.nextC)

}
